intExpr(DT,T):-intTerm(DT,T).
intExpr(DE+DT,E+T):-intTerm(DE,E),intExpr(DT,T).
intExpr(DE-DT,E-T):-intTerm(DE,E),intExpr(DT,T).

%per parti
intTerm(K*DT,K*T):-number(K),intExpr(DT,T).
intTerm(DT*DE,R):-semplifica(DT*DE,DX),intTerm(DX,R).
intTerm(DT*E,T*E-Int):-intFactor(DT,T),dFactor(E,DE),intTerm(T*DE,Int).
intTerm(E*DT,E*T-Int):-intFactor(DT,T),dFactor(E,DE),intTerm(T*DE,Int).
intTerm(DF,F):-intFactor(DF,F).

intFactor(-DE,-E):-intExpr(DE,E).
intFactor([DE],E):-intExpr(DE,E).
intFactor(1,x).
intFactor(N,N*x):-number(N).
intFactor(x,x^2/2).
intFactor(x^K,x^N/N):-number(K),N is K+1.
intFactor(x^K/Q,x^N/P):- number(K), N is K+1, P is Q*N.
intFactor(F^N*DF,F^M/M):- not(N is -1),M is N+1,intFactor(DF,F).
intFactor(1/x,log(x)).
intFactor(cos(x),sin(x)).
intFactor(sin(x),-cos(x)).
intFactor(cos(E)*DE,sin(E)):-dFactor(E,DE).
intFactor(sin(E)*DE,-cos(E)):-dFactor(E,DE).
intFactor(exp(X)*DX,exp(X)):-intExpr(DX,X).
intFactor(exp(K*x),exp(x)/K):- number(K).
intFactor(exp(x),exp(x)).
intFactor(1+(tg(x)^2),tg(x)).
intFactor(1+(cotg(x)^2),-cotg(x)).
intFactor(a^x,a^x/log(a)).


dExpr(T,DT)	 :-dTerm(T,DT).
dExpr(E+T,DE+DT) :-dExpr(E,DE),dTerm(T,DT).
dExpr(E+T,DE-DT) :-dExpr(E,DE),dTerm(T,DT).

dTerm(F,DF)                      :-dFactor(F,DF).
dTerm(T*F,[DT*F]+[T*DF])       :-dTerm(T,DT),dFactor(F,DF).
dTerm(T/F,[[DT*F]-[T*DF]]/[F*F]) :-dTerm(T,DT),dFactor(F,DF).

dFactor(x,1).
dFactor(x^K,K*x^N)	     :-number(K),N is K-1.
dFactor(N,0)                 :-number(N).
dFactor([E],DE)              :-dExpr(E,DE).
dFactor(-E,-DE)              :-dExpr(E,DE).
dFactor(sin(E),DE*cos(E))  :-dExpr(E,DE).
dFactor(cos(E),-DE*sin(E)) :-dExpr(E,DE).
dFactor(log(E),DE/E)	     :-dExpr(E,DE).
dFactor(exp(E),exp(E)*DE)    :-dExpr(E,DE).

semplifica(0*_,0).
semplifica(X*1,X).
semplifica(1*X,X).
semplifica(K*x^1,K*x).
semplifica(x*(K/x),K).
semplifica(N*x*(K/x),R):-R is N*K.
semplifica(K/x*(x),K).
semplifica(P/x*(x^K/R),P*(x^Q/R)):-Q is K-1.
semplifica(x^K/R*(P/x),P*(x^Q/R)):-Q is K-1.
semplifica(P/x^K*(x^Q/R),P*(x^T/R)):-T is Q-K,T>0.
semplifica(P/x^K*(x^Q/R),P/(x^T*R)):-T is K-Q.
semplifica(x^Q/R*(P/x^K),P*(x^T/R)):-T is Q-K,T>0.
semplifica(x^Q/R*(P/x^K),P/x^T*R):-T is K-Q.




